<template>
  <span>{{ displayValue }}</span>
</template>

<script>
import { ref, onMounted, watch } from 'vue';

export default {
  name: 'CountTo',
  props: {
    startVal: {
      type: Number,
      default: 0
    },
    endVal: {
      type: Number,
      required: true
    },
    duration: {
      type: Number,
      default: 2000
    },
    decimals: {
      type: Number,
      default: 0
    },
    separator: {
      type: String,
      default: ''
    },
    prefix: {
      type: String,
      default: ''
    },
    suffix: {
      type: String,
      default: ''
    },
    autoplay: {
      type: Boolean,
      default: true
    }
  },
  setup(props) {
    // 格式化值
    const formatValue = (value) => {
      const fixedValue = parseFloat(value).toFixed(props.decimals);
      let formattedValue = fixedValue;
      
      // 添加分隔符
      if (props.separator) {
        const parts = fixedValue.toString().split('.');
        parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, props.separator);
        formattedValue = parts.join('.');
      }
      
      // 添加前缀和后缀
      return props.prefix + formattedValue + props.suffix;
    };
    
    const localStartVal = ref(props.startVal);
    const displayValue = ref(formatValue(props.startVal));
    const localDuration = ref(props.duration);
    let lastTimestamp = 0;
    let rAF = null;
    let startTime = 0;
    
    const countUp = (timestamp) => {
      if (!startTime) startTime = timestamp;
      const progress = timestamp - startTime;
      
      if (progress < localDuration.value) {
        // 计算当前值
        const currentValue = easeOutQuart(
          progress,
          localStartVal.value,
          props.endVal - localStartVal.value,
          localDuration.value
        );
        
        // 显示当前值
        displayValue.value = formatValue(currentValue);
        
        // 继续动画
        rAF = requestAnimationFrame(countUp);
      } else {
        // 结束动画
        displayValue.value = formatValue(props.endVal);
      }
    };
    
    // 缓动函数
    const easeOutQuart = (t, b, c, d) => {
      return -c * ((t = t / d - 1) * t * t * t - 1) + b;
    };
    
    // 开始计数
    const start = () => {
      localStartVal.value = props.startVal;
      startTime = 0;
      localDuration.value = props.duration;
      rAF = requestAnimationFrame(countUp);
    };
    
    // 停止计数
    const stop = () => {
      if (rAF) {
        cancelAnimationFrame(rAF);
        rAF = null;
      }
    };
    
    // 重置计数
    const reset = () => {
      stop();
      displayValue.value = formatValue(props.startVal);
    };
    
    // 恢复计数
    const resume = () => {
      stop();
      startTime = 0;
      localDuration.value = props.duration * (props.endVal - displayValue.value) / (props.endVal - localStartVal.value);
      rAF = requestAnimationFrame(countUp);
    };
    
    // 监听endVal变化
    watch(() => props.endVal, (newVal) => {
      stop();
      localStartVal.value = parseFloat(displayValue.value.replace(/[^\d.-]/g, ''));
      start();
    });
    
    // 组件挂载后自动开始
    onMounted(() => {
      if (props.autoplay) {
        start();
      }
    });
    
    return {
      displayValue,
      start,
      stop,
      reset,
      resume
    };
  }
};
</script> 